/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package drinkcounter.web.controllers.api;

import com.csvreader.CsvWriter;
import com.google.common.base.Charsets;
import drinkcounter.DrinkCounterService;
import drinkcounter.HistoryService;
import drinkcounter.model.Participant;
import drinkcounter.model.ParticipantHistory;
import drinkcounter.model.PartyHistory;
import drinkcounter.util.DrinkCounterCache;
import drinkcounter.util.PartyMarshaller;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 *
 * @author Toni
 */
@Controller
public class APIController {

    private static final Logger log = LoggerFactory.getLogger(APIController.class);

    @Autowired
    private DrinkCounterCache cache;

    @Autowired
    private PartyMarshaller partyMarshaller;

    @Autowired
    private DrinkCounterService service;

    @Autowired
    private HistoryService historyService;

    @RequestMapping("/{partyId}")
    public void printXml(@PathVariable String partyId, HttpServletResponse res) throws IOException{
        res.setCharacterEncoding("UTF-8");
        res.setContentType("text/html; charset=UTF-8");
        Writer writer = res.getWriter();
        try{
            byte[] cached = cache.getPartyDrinksCache(partyId);
            if(cached != null){
                printBytes(cached, writer);
            }else{
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                partyMarshaller.marshall(partyId, baos);
                byte[] bytesXml = baos.toByteArray();
                cache.setPartyDrinksCache(partyId, bytesXml);
                printBytes(bytesXml, writer);
            }
        }finally{
            writer.close();
        }
        
    }

    @RequestMapping("/{partyId}/add-drink")
    public void addDrink(@PathVariable String partyId, @RequestParam("participant-id") String participantId,  Writer writer){
        PrintWriter out = new PrintWriter(writer);
        service.addDrink(participantId);
        Participant participant = service.getParticipant(participantId);
        out.print(participant.getTotalDrinks());
        out.close();
    }

    @RequestMapping("/{partyId}/add-participant")
    public void addDrink(@PathVariable String partyId,
            @RequestParam("name") String name,
            @RequestParam("sex") String sex,
            @RequestParam("weight") float weight,
            Writer writer){
        Participant participant = new Participant();
        participant.setName(name);
        participant.setSex(Participant.Sex.valueOf(sex));
        participant.setWeight(weight);
        participant = service.addParticipant(participant, partyId);
        PrintWriter out = new PrintWriter(writer);
        out.print(participant.getId());
        out.close();
    }

    @RequestMapping("/{partyId}/remove-participant")
    public void removeParticipant(@RequestParam("participant-id") String participantId){
        service.deleteParticipant(participantId);
    }

    @RequestMapping("/{partyId}/show-history")
    public void showHistory(@PathVariable String partyId, HttpServletResponse res) throws IOException{
        res.setCharacterEncoding("UTF-8");
        res.setContentType("text/html; charset=UTF-8");
        PrintWriter out = res.getWriter();
        try{
            byte[] cachedHistory = cache.getPartyHistoryCache(partyId);
            if(cachedHistory != null){
                log.info("Loading history from cache for party {}", partyId);
                printBytes(cachedHistory, out);
            }else{
                log.info("History cache for party {} not found, creating csv", partyId);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                CsvWriter csvWriter = new CsvWriter(new OutputStreamWriter(baos, Charsets.UTF_8), ',');
                csvWriter.writeRecord(new String[]{"Time", "Name", "Alcohol Level", "Drinks"});
                List<PartyHistory> partyHistories = historyService.getPartyHistory(partyId);
                for (PartyHistory partyHistory : partyHistories) {
                    DateTime time = new DateTime(partyHistory.getSnapshotTime());
                    for (ParticipantHistory participantHistory : partyHistory.getParticipants()) {
                        csvWriter.writeRecord(
                                new String[]{
                                    time.toString(),
                                    participantHistory.getParticipantName(),
                                    Float.toString(participantHistory.getAlcoholLevel()),
                                    participantHistory.getTotalDrinks().toString()
                                }
                        );
                    }
                }
                csvWriter.close();
                byte[] bytes = baos.toByteArray();
                cache.setPartyHistoryCache(partyId, bytes);
                printBytes(bytes, out);
            }
        }finally{
            out.close();
        }
    }

    private void printBytes(byte[] bytes, Writer writer) throws IOException{
        IOUtils.copy(new InputStreamReader(new ByteArrayInputStream(bytes), "UTF-8"), writer);
    }
}
